package com.vcaresolution.logistic.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.vcaresolution.logistic.form.BranchForm;
import com.vcaresolution.logistic.jsonbean.BranchJson;
import com.vcaresolution.logistic.jsonbean.DepartmentJson;
import com.vcaresolution.logistic.pojo.Branch;
import com.vcaresolution.logistic.pojo.City;
import com.vcaresolution.logistic.pojo.Company;
import com.vcaresolution.logistic.pojo.Department;
import com.vcaresolution.logistic.to.BranchTO;
import com.vcaresolution.logistic.to.DataHolderTO;
import com.vcaresolution.logistic.to.DepartmentTO;
import com.vcaresolution.logistic.util.ApplicationConstants;
import com.vcaresolution.util.Utils;

@Service
public class BranchServiceImpl extends BaseService implements BranchService{

	private Branch populateBranchPojo(BranchForm branchForm){
		Branch branch = new Branch();
		BeanUtils.copyProperties(branchForm, branch);
		
		return branch;
	}

	@Override
	@Transactional
	public void add(BranchForm branchForm) {
		Branch branch = populateBranchPojo(branchForm);
		branch.setCity(getDaoFactory().getUtilityDAO().findById(City.class, branchForm.getCityId()));
		branch.setCompany(getDaoFactory().getUtilityDAO().findById(Company.class, branchForm.getCompanyId()));

		branch.setCreationdate(Utils.getCurrentDate());
		branch.setAuditdate(Utils.getCurrentDate());
		
		//Setting Default Status as Active 
		branch.setIsactive(ApplicationConstants.ACTIVE_STATUS);
		
		getDaoFactory().getUtilityDAO().add(branch);
		
	}

	@Override
	@Transactional
	public void update(BranchForm branchForm) {
		Branch branch = populateBranchPojo(branchForm);
		branch.setCity(getDaoFactory().getUtilityDAO().findById(City.class, branchForm.getCityId()));
		branch.setCompany(getDaoFactory().getUtilityDAO().findById(Company.class, branchForm.getCompanyId()));
		branch.setCreationdate(Utils.getCurrentDate());
		
		getDaoFactory().getUtilityDAO().update(branch);
	}

	@Override
	@Transactional
	public void delete(BranchForm branchForm) {
		getDaoFactory().getUtilityDAO().delete(populateBranchPojo(branchForm));
		
	}

	@Override
	@Transactional
	public BranchTO findById(Serializable branchId) {
		
		Branch branch = (Branch) getDaoFactory().getUtilityDAO().findById(Branch.class,branchId);
		
		BranchTO branchTO = new BranchTO();
		BeanUtils.copyProperties(branch, branchTO);
		
		branchTO.setCityId(branch.getCity().getCityid());
		
		return branchTO; 
	}

	@Override
	@Transactional
	public List<BranchTO> findByAll()
	{
		List<Branch> branchList = (List<Branch>) getDaoFactory().getUtilityDAO().findByAll(Branch.class);
		return ((List<BranchTO>) Utils.copyProperties(branchList, BranchTO.class));
	}

	/**#editedByVishal*/
	/*@Override
	@Transactional
	public List<DepartmentTO> getAssociatedDepartmentList(Serializable branchId) {
		List<DepartmentTO> departmentTOList = new ArrayList<DepartmentTO>();
		
		List<Department> associatedDepartmentList = getDaoFactory().getBranchDAO().getAssociatedDepartmentList(branchId);
		if( associatedDepartmentList != null && !associatedDepartmentList.isEmpty() ){
			DepartmentTO departmentTO = null;
			for(Department department : associatedDepartmentList){
				departmentTO = new DepartmentTO();
				
				BeanUtils.copyProperties(department, departmentTO);
				departmentTOList.add(departmentTO);
			}
		}
		
		return departmentTOList;
	}*/
	
	/**#editedByVishal*/
	@Override
	@Transactional
	public List<DepartmentTO> getAssociatedDepartmentList(Serializable branchId) {
		List<DepartmentTO> departmentTOList = new ArrayList<DepartmentTO>();
		
		List<Department> associatedDepartmentList = getDaoFactory().getBranchDAO().getAssociatedDepartmentList(branchId);
		if( associatedDepartmentList != null && !associatedDepartmentList.isEmpty() ){
			DepartmentTO departmentTO = null;
			for(Department department : associatedDepartmentList){
				departmentTO = new DepartmentTO();
				
				BeanUtils.copyProperties(department, departmentTO);
				departmentTOList.add(departmentTO);
			}
		}
		
		return departmentTOList;
	}
	
	/*@SuppressWarnings("unchecked")
	public <T> List<T> getAssociatedDepartmentList(Serializable branchId,Class<T> returnType) 
	{
		List<T> departmentTOList = new ArrayList<T>();
		try
		{
			List<Department> associatedDepartmentList = getDaoFactory().getBranchDAO().getAssociatedDepartmentList(branchId);
			if( associatedDepartmentList != null && !associatedDepartmentList.isEmpty() )
			{
				T instance = null;
				DataHolderTO dataHolder = null;
				for(Department department : associatedDepartmentList)
				{
					instance = returnType.newInstance();
					if(returnType == DataHolderTO.class)
					{
						dataHolder = (DataHolderTO)instance;
						dataHolder.setFieldId(department.getDepartmentid());
						dataHolder.setFieldname(department.getDepartmentname());
						departmentTOList.add((T)dataHolder);
					}
					else if(returnType == DepartmentTO.class)
					{
						BeanUtils.copyProperties(department, instance);
						departmentTOList.add(instance);
					}
					else 
					{
						System.out.println(returnType.getName() + "is not valid class for return type # BranchServiceImpl.getAssociatedDepartmentList");
					}
				}
			}
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		return departmentTOList;
	}*/
	
	
	{
		/*
			"data":[{
				"branch":{
					"id":"1",
					"name":"1stB"
				},
				"departments":[{
					"id":"1",
					"name":"1stD"
				},{
					"id":"2",
					"name":"2stD"
				}]
			 },{
				"branch":{
					"id":"1",
					"name":"1stB"
				},
				"departments":[{
					"id":"1",
					"name":"1stD"
				},{
					"id":"2",
					"name":"2stD"
				}]
			 }];    
       
       
		 * */
	}
	
	@Override
	@Transactional
	public Map<String, ? extends Object> getAssociatedDepartmentList(Set<Integer> branchIdSet) 
	{
		Map<String, Object> finalData = new HashMap<String, Object>();
		List<BranchJson> branches = new ArrayList<BranchJson>();
		BranchJson branchJson = null;
		DepartmentJson departmentJson = null;
		Branch branch = null;
		List<DepartmentJson> departmentJsonList = null;
		List<Department> associatedDepartmentList = null;
		Integer branchId = null;
		
		Iterator<Integer> branchIdIterator = branchIdSet.iterator();
		
		while (branchIdIterator.hasNext()) 
		{
			branchId = (Integer) branchIdIterator.next();
			branch = getDaoFactory().getBranchDAO().findById(Branch.class, branchId);
			branchJson = new BranchJson();
			branchJson.setBranchid(branch.getBranchid());
			branchJson.setBranchname(branch.getBranchname());
			branchJson.setBranchcode(branch.getBranchcode());
			
			associatedDepartmentList = getDaoFactory().getBranchDAO().getAssociatedDepartmentList(branchId);
			if(associatedDepartmentList != null && !associatedDepartmentList.isEmpty())
			{
				departmentJsonList = new ArrayList<DepartmentJson>();
				for(Department department : associatedDepartmentList)
				{
					departmentJson = new DepartmentJson();
					departmentJson.setDepartmentid(department.getDepartmentid());
					departmentJson.setDepartmentname(department.getDepartmentname());
					departmentJsonList.add(departmentJson);
				}
				branchJson.setDepartments(departmentJsonList);
			}
			branches.add(branchJson);
		}
		
		finalData.put("data", branches);
		finalData.put("totalCount", branches.size());
		finalData.put("success", true);
		return finalData;		
	}
}